package org.enhance.common.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.ttl.TransmittableThreadLocal;

public abstract class DateFormatUtil {

	private static transient Logger logger = LoggerFactory.getLogger(DateFormatUtil.class);

	public static final String COMPACT_YEARMONTH_FORMAT = "yyyyMM";
	public static final String COMPACT_DATE_FORMAT = "yyyyMMdd";
	public static final String COMPACT_DATETIME_FORMAT = "yyyyMMddHHmmss";
	public static final String DATETIME_NOSPLIT_FORMAT = "yyyyMMdd HH:mm:ss";
	public static final String YEARMONTH_FORMAT = "yyyy-MM";
	public static final String DATE_FORMAT = "yyyy-MM-dd";
	public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	public static final String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
	public static final String LOCALE_FORMAT = "EEE MMM dd HH:mm:ss z yyyy";

	private static InheritableThreadLocal<DateFormat> compactYearmonthFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(COMPACT_YEARMONTH_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> compactDateFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(COMPACT_DATE_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> compactDatetimeFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(COMPACT_DATETIME_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> yearmonthFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(YEARMONTH_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> datetimeFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(DATETIME_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> datetimeWithNoSplitFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(DATETIME_NOSPLIT_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> dateFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(DATE_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> rfc3339DateFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(RFC3339_FORMAT);
		}
	};

	private static InheritableThreadLocal<DateFormat> localeFormat = new TransmittableThreadLocal<DateFormat>() {
		@Override
		protected synchronized DateFormat initialValue() {
			return new SimpleDateFormat(LOCALE_FORMAT);
		}
	};


	public static DateFormat getCompactYearmonthFormat() {
		return compactYearmonthFormat.get();
	}

	public static DateFormat getCompactDateFormat() {
		return compactDateFormat.get();
	}

	public static DateFormat getCompactDatetimeFormat() {
		return compactDatetimeFormat.get();
	}

	public static DateFormat getDatetimeWithNoSplitFormat() {
		return datetimeWithNoSplitFormat.get();
	}

	public static DateFormat getYearmonthFormat() {
		return yearmonthFormat.get();
	}

	public static DateFormat getDateFormat() {
		return dateFormat.get();
	}

	public static DateFormat getDatetimeFormat() {
		return datetimeFormat.get();
	}

	public static DateFormat getRfc3339DateFormat() {
		return rfc3339DateFormat.get();
	}

	public static DateFormat getLocaleFormat() {
		return localeFormat.get();
	}

	public static Date parseCompactYearmonth(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getCompactYearmonthFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, COMPACT_YEARMONTH_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseCompactDate(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getCompactDateFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, COMPACT_DATE_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseCompactDatetime(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getCompactDatetimeFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, COMPACT_DATETIME_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseDatetimeWithNoSplit(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getDatetimeWithNoSplitFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, DATETIME_NOSPLIT_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseYearmonth(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getYearmonthFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, YEARMONTH_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseDate(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getDateFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, DATE_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseDatetime(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getDatetimeFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, DATETIME_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parseRfc3339DateFormat(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getRfc3339DateFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, RFC3339_FORMAT, e.getMessage());
		}
		return null;
	}

	/**
	 * @param dateStr 形如：Thu May 28 18:23:17 CST 2015
	 * @return
	 */
	public static Date parseLocale(String dateStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			return getLocaleFormat().parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, LOCALE_FORMAT, e.getMessage());
		}
		return null;
	}

	public static Date parse(String dateStr, String formatStr) {
		try {
			if (dateStr.startsWith("'") && dateStr.endsWith("'")) {
				dateStr = dateStr.substring(1, dateStr.length() - 1);
			}
			DateFormat format = new SimpleDateFormat(formatStr);
			return format.parse(dateStr);
		} catch (ParseException e) {
			logger.error("日期格式转换失败:{}->{};{}", dateStr, formatStr, e.getMessage());
		}
		return null;
	}

	public static String toCompactYearmonth(Date date) {
		return date != null ? getCompactYearmonthFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toCompactDate(Date date) {
		return date != null ? getCompactDateFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toCompactDatetime(Date date) {
		return date != null ? getCompactDatetimeFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toDatetimeWithNoSplit(Date date) {
		return date != null ? getDatetimeWithNoSplitFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toYearmonth(Date date) {
		return date != null ? getYearmonthFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toDate(Date date) {
		return date != null ? getDateFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toDatetime(Date date) {
		return date != null ? getDatetimeFormat().format(date) : StringUtils.EMPTY;
	}

	public static String toRfc3339Date(Date date) {
		return date != null ? getRfc3339DateFormat().format(date) : StringUtils.EMPTY;
	}

	public static String format(Date date, String formatStr) {
		DateFormat dateFormat = new SimpleDateFormat(formatStr);
		return date != null ? dateFormat.format(date) : StringUtils.EMPTY;
	}
}
